#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "crypto/types.h"
#include "crypto/bits.h"
#include "crypto/errors.h"
#include "crypto/destool.h"

// 产生源密钥
void generateOriginalCryptoKey(byte *buffer)
{
    byte randomString[7];
    int fd = open("/dev/urandom", O_RDONLY);
    if (fd == -1)
    {
        export(CODE_FILE_OPERATE_FAILED, "File /dev/urandom open failed!");
    }
    int ret = read(fd, randomString, 7);
    close(fd);
    int index = 0;
    byte tmp;
    byte checkDigit = 0;
    for (int i = 0; i < 8; i++)
    {
        do
        {
            if (getBitFromArray(randomString, index))
            {
                checkDigit++;
                tmp += 1;
            }
            index += 1;
            tmp = tmp << 1;
        } while (index % 7 != 0);
        tmp << 1;
        if (checkDigit % 2)
        {
            tmp += 1;
        }
        buffer[i] = tmp;
        tmp = 0;
        checkDigit = 0;
    }
}
// des入口
void des(byte *text, byte *cryptoText, byte *desOriginKey, uint len, CRYPTO_OPT opt)
{
    int group = len / 8;
    int mod = len % 8;
    bits *LR[2];
    bits *tepBit;
    bits *cryptoKey = desGetCryptoKey(desOriginKey);
    bits *subCryptoKeys[16];
    bits *Rint = initBits(DES_SUB_KEY_BIT_LEN);

    for (int i = 0; i < 16; i++)
    {
        subCryptoKeys[i] = initBits(DES_SUB_KEY_BIT_LEN);
    }

    desGetSubCryptoKeys(subCryptoKeys, cryptoKey, opt);

    free(cryptoKey);

    LR[0] = initBits(4 * 8);
    LR[1] = initBits(4 * 8);

    for (int i = 0; i < group; i++)
    {
        desInitData(LR, text + i * 8);
        for (int j = 0; j < 16; j++)
        {
            desRound(LR, subCryptoKeys[j], Rint);
        }
        desFinalTrans(LR);
        memcpy(cryptoText + i * 8, LR[0]->data, 4);
        memcpy(cryptoText + i * 8 + 4, LR[1]->data, 4);
    }

    if (mod == 0)
    {
        cryptoText[len] = 0;

        free(LR[0]);
        free(LR[1]);
        free(Rint);
        for (int i = 0; i < 16; i++)
        {
            free(subCryptoKeys[i]);
        }
        return;
    }

    byte buffer[8];
    memset(buffer, 0, 8);
    memcpy(buffer, text + group * 8, len - group * 8);

    desInitData(LR, buffer);
    for (int i = 0; i < 16; i++)
    {
        desRound(LR, subCryptoKeys[i], Rint);
    }
    desFinalTrans(LR);
    memcpy(cryptoText + group * 8, LR[0]->data, 4);
    memcpy(cryptoText + group * 8 + 4, LR[1]->data, 4);
    cryptoText[(group + 1) * 8] = 0;

    free(LR[0]);
    free(LR[1]);
    free(Rint);
    for (int i = 0; i < 16; i++)
    {
        free(subCryptoKeys[i]);
    }

    return;
}

void generateFinalDesKey(uint64 clientRandom, uint64 serverRandom, uint64 premasterKey, char *DesKey)
{
    clientRandom ^= serverRandom;
    clientRandom ^= premasterKey;
    for (int i = 0; i < 8; i++)
    {
        DesKey[i] = clientRandom % 256;
        clientRandom /= 256;
    }
}